package commons.meta.impl.hibernate;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import commons.BizException;
import commons.conf.ResourceDomain;
import commons.groovy.GroovyInstance;
import commons.meta.RuntimeApplication;
import commons.meta.RuntimeDomainObject;
import commons.meta.impl.DomainGenerater;
import commons.template.FtlTemplate;

/**
 * Generate Hibernate java or groovy Entity
 * @author jkyang
 */
public class HibernateDomainGenerater implements DomainGenerater{

	private static Log log = LogFactory.getLog(HibernateDomainGenerater.class);
	
//	private String basePath = "classpath:" + HibernateDomainGenerater.class.getPackage().getName().replaceAll("\\.", "/") + "/";
	
//	private SimpleTemplateEngine engine = new SimpleTemplateEngine();
	
//	private String getPath(String fileName) {
//		return basePath + fileName; 
//	}
	private RuntimeApplication application ;
	
	public HibernateDomainGenerater(RuntimeApplication application) {
		this.application = application ;
	}
	
	private String classResource(String fileName, Map<String, Object> value) {
		return FtlTemplate.getTemplate(fileName, value);
	}
	
	public RuntimeDomainObject generate(ResourceDomain domainResource) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("domain", domainResource);
		String clazzRes = classResource("Domain.groovy.ftl", map);
		log.debug("\n" + clazzRes);
		//TODO
//		GroovyInstance.loadObject(clazzRes);
		/*
		GroovyObject go = GroovyInstance.parseObject(clazzRes);
		log.debug(go);
		if( go== null) {
			throw new BizException("Domain Template parser Error!!!");
		}
		System.out.println(ToStringBuilder.reflectionToString(go));
		*/
		return null;
	}

	public List<RuntimeDomainObject> generate(List<ResourceDomain> domainResources) {
		log.debug("find domains:" + domainResources.size());
		List<RuntimeDomainObject> list = new ArrayList<RuntimeDomainObject>();
		if(domainResources != null) {
			for (int i = 0; i < domainResources.size(); i++) {
				list.add(generate(domainResources.get(i)));
			}
		}
		return list;
	}
	
	public void compiler(List<ResourceDomain> domainResources, List<File> hbmXmlFiles) {
		log.debug("find domains:" + domainResources.size());
		if(domainResources != null) {
			for (int i = 0; i < domainResources.size(); i++) {
				compiler(domainResources.get(i));
			}
		}
		load(domainResources, hbmXmlFiles);
	}

	private void load(List<ResourceDomain> domainResources, List<File> hbmXmlFiles) {
		if(domainResources != null) {
			for (int i = 0; i < domainResources.size(); i++) {
				load(domainResources.get(i), hbmXmlFiles);
				loadHbmXml(domainResources.get(i), hbmXmlFiles); 
			}
		}
	}
	
	private void loadHbmXml(ResourceDomain resourceDomain, List<File> hbmXmlFiles) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("domain", resourceDomain);
		String xmlRes = classResource("Domain.hbm.xml.ftl", map);
		try {
			File file = File.createTempFile(resourceDomain.getDomainName() + ".hbm.", ".xml");
			FileUtils.writeStringToFile(file, xmlRes, "utf-8");
			hbmXmlFiles.add(file);
		} catch (IOException e) {
			e.printStackTrace();
			throw new BizException(e);
		}
		log.debug("compiler second:\n" + xmlRes);
	}

	private void load(ResourceDomain domainResource, List<File> hbmXmlFiles) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("domain", domainResource);
		String clazzRes = classResource("Domain.groovy.ftl", map);
		log.debug("compiler second:\n" + clazzRes);
		GroovyInstance.loadObject(this.application.getClassLoader(), clazzRes);
	}
	
	public void compiler(ResourceDomain domainResource) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("domain", domainResource);
		String clazzRes = classResource("EmptyDomain.groovy.ftl", map);
		log.debug("compiler first:" + domainResource.getFullName());
		GroovyInstance.loadObject(this.application.getClassLoader(), clazzRes);
	}
	
}
